<?php
/**
 * Pagination library.
 *
 * $Id: pagination.class.php 24762 2012-09-03 14:21:04Z xuwh $
 *
 * @package    Core
 * @author     Kohana Team
 * @copyright  (c) 2007-2008 Kohana Team
 * @license    http://kohanaphp.com/license.html
 */
class Pagination
{
	// Config values
	protected $base_url = '';

	protected $directory = 'pagination';

	protected $style = 'classic';

	protected $uri_segment = 3;

	protected $query_string = '';

	protected $items_per_page = 20;

	protected $total_items = 0;

	protected $auto_hide = FALSE;

	protected $current_page;
	// url默认模板
	protected $url;
	// Autogenerated values
	protected $total_pages;

	protected $current_first_item;

	protected $current_last_item;

	protected $first_page;

	protected $last_page;

	protected $previous_page;

	protected $next_page;

	protected $sql_offset;

	protected $sql_limit;

	/**
	 * Constructs and returns a new Pagination object.
	 *
	 * @param
	 *       	 array configuration settings
	 * @return object
	 */
	public static function factory ($config = array())
	{
		$class = get_called_class();
		return new $class($config);
	}

	/**
	 * Constructs a new Pagination object.
	 *
	 * @param
	 *       	 array configuration settings
	 * @return void
	 */
	public function __construct ($config = array())
	{
		$this->setup_config($config);
		// Pagination setup
		$this->initialize();
	}

	public function setup_config ($config)
	{
		// No custom group name given
		if (! isset($config['group'])) $config['group'] = 'default';
		// Load config group
		if (isset($config['group']))
		{
			// Load and validate config group
			$pagination_config = func::get_cfg('pagination');
			$default_config = $pagination_config['default'];
			$group_config = array();
			if (isset($pagination_config[$config['group']]))
			{
				$group_config = $pagination_config[$config['group']];
			}
			// All pagination config groups inherit default config group
			if ($config['group'] !== 'default')
			{
				$group_config += $default_config;
			}
			// Merge custom config items with config group
			$config += $group_config;
		}
		// Assign config values to the object
		$this->set_from($config);
	}

	/**
	 * 设置对象属性
	 *
	 * @param $options array       	
	 */
	protected function set_from ($options)
	{
		foreach ($options as $key => $value)
		{
			if (property_exists($this, $key))
			{
				$this->$key = $value;
			}
		}
	}

	protected function mk_url ()
	{
		// Clean view directory
		if ($this->base_url === '') $this->base_url = $this->get_request_uri();
		if ($this->query_string !== '')
		{
			// Extract current page
			// $this->current_page = isset($_GET[$this->query_string]) ? (int)
			// $_GET[$this->query_string] : 1;
			// Insert {page} placeholder
			$_GET[$this->query_string] = '{page}';
			// Create full URL
			if (! $this->url) $this->url = "{$this->base_url}?" . str_replace('%7Bpage%7D', '{page}', http_build_query($this->get_args()));
			// Reset page number
			$_GET[$this->query_string] = $this->current_page;
		}
		// Build generic URL with page as URI segment
		else
		{
			// Use current URI if no base_url set
			$this->url = explode('/', trim($this->base_url, '/'));
			// Convert uri 'label' to corresponding integer if needed
			// Insert {page} placeholder
			$this->url[$this->uri_segment - 1] = '{page}';
			// Create full URL
			$this->url = '/' . implode('/', $this->url) . '?' . http_build_query($this->get_args());
			// Extract current page
			// $this->current_page = $this->segment($this->uri_segment);
		}
	}

	/**
	 * Sets config values.
	 *
	 * @throws Kohana_Exception
	 * @param
	 *       	 array configuration settings
	 * @return void
	 */
	protected function initialize ()
	{
		// Build generic URL with page in query string
		if (! $this->url) $this->mk_url();
		// Core pagination values
		$this->total_items = (int) max(0, $this->total_items);
		$this->items_per_page = (int) max(1, $this->items_per_page);
		$this->total_pages = (int) ceil($this->total_items / $this->items_per_page);
		$this->current_page = (int) min(max(1, $this->current_page), max(1, $this->total_pages));
		$this->current_first_item = (int) min((($this->current_page - 1) * $this->items_per_page) + 1, $this->total_items);
		$this->current_last_item = (int) min($this->current_first_item + $this->items_per_page - 1, $this->total_items);
		// If there is no first/last/previous/next page, relative to the
		// current page, value is set to FALSE. Valid page number otherwise.
		$this->first_page = ($this->current_page === 1) ? FALSE : 1;
		$this->last_page = ($this->current_page >= $this->total_pages) ? FALSE : $this->total_pages;
		$this->previous_page = ($this->current_page > 1) ? $this->current_page - 1 : FALSE;
		$this->next_page = ($this->current_page < $this->total_pages) ? $this->current_page + 1 : FALSE;
		// SQL values
		$this->sql_offset = (int) ($this->current_page - 1) * $this->items_per_page;
		$this->sql_limit = sprintf(' LIMIT %d OFFSET %d ', $this->items_per_page, $this->sql_offset);
		$this->url = str_replace('{total_items}', $this->total_items, $this->url);
	}

	public function get_request_uri ()
	{
		static $uri = NULL;
		if (! $uri)
		{
			if (! isset($_SERVER['REQUEST_URI'])) $uri = '/';
			$splitor = strpos($_SERVER['REQUEST_URI'], '?') ? '?' : '&';
			$uri = strstr($_SERVER['REQUEST_URI'], $splitor, TRUE);
		}
		return $uri;
	}

	public function segment ($pos)
	{
		$uri = $this->get_request_uri();
		$segments = explode('/', trim($uri, '/'));
		-- $pos;
		return isset($segments[$pos]) ? $segments[$pos] : NULL;
	}

	public function get_args ()
	{
		$args = $_GET;
		unset($args['action'], $args['arg1'], $args['arg2']);
		return $args;
	}

	/**
	 * Generates the HTML for the chosen pagination style.
	 *
	 * @param
	 *       	 string pagination style
	 * @return string pagination html
	 */
	public function render ($style = NULL)
	{
		if($this->total_pages<2)return '';
		// Hide single page pagination
		if ($this->auto_hide === TRUE and $this->total_pages <= 1) return '';
		if ($style === NULL)
		{
			// Use default style
			$style = $this->style;
		}
		// Return rendered pagination view
		// return View::factory($this->directory.$style,
		// get_object_vars($this))->render();
		$_data = get_object_vars($this);
		extract($_data, EXTR_SKIP);
		ob_start();
		include "views/{$this->directory}/{$style}.php";
		$rs = ob_get_clean();
		return $rs;
	}

	/**
	 * Magically converts Pagination object to string.
	 *
	 * @return string pagination html
	 */
	public function __toString ()
	{
		return $this->render();
	}

	/**
	 * Magically gets a pagination variable.
	 *
	 * @param
	 *       	 string variable key
	 * @return mixed variable value if the key is found
	 * @return void if the key is not found
	 */
	public function __get ($key)
	{
		if (isset($this->$key)) return $this->$key;
	}

	/**
	 * Adds a secondary interface for accessing properties, e.g.
	 * $pagination->total_pages().
	 * Note that $pagination->total_pages is the recommended way to access
	 * properties.
	 *
	 * @param
	 *       	 string function name
	 * @return string
	 */
	public function __call ($func ,$args = NULL)
	{
		return $this->__get($func);
	}
} // End Pagination Class